From 8cb7d049113ca88d6a89f2746620a5f4e2b4b228 Mon Sep 17 00:00:00 2001 From: robertl Date: Thu, 23 Nov 2006 03:34:59 +0000 Subject: [PATCH] Enhance PCX reader to handle (some) files from GPSUtil. --- pcx.c | 94 +++++++++++++++++++++++++++++++++++------ reference/gpsutil-1.pcx | 23 ++++++++++ testo | 3 ++ 3 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 reference/gpsutil-1.pcx diff --git a/pcx.c b/pcx.c index b6c33d66d..3b75de0f0 100644 --- a/pcx.c +++ b/pcx.c @@ -2,7 +2,7 @@ Access to Garmin PCX5 files. Format described in: http://www.garmin.com/manuals/PCX5_OwnersManual.pdf - Copyright (C) 2002-2005 Robert Lipe, robertlipe@usa.net + Copyright (C) 2002-2006 Robert Lipe, robertlipe@usa.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include "defs.h" #include "garmin_tables.h" +#include "csv_util.h" #include static gbfile *file_in, *file_out; @@ -30,7 +31,12 @@ static short_handle mkshort_handle2; /* for track and route names */ static char *deficon = NULL; static char *cartoexploreur; static int read_as_degrees; +static int read_gpsu; static int route_ctr; +static int comment_col = 60; /* This has a default */ +static int sym_col; +static int lat_col; +static int lon_col; #define MYNAME "PCX" @@ -75,9 +81,8 @@ wr_deinit(void) static void data_read(void) { - char name[7], desc[40]; + char name[7], desc[41]; double lat,lon; - char latdir, londir; long alt; int symnum; char date[10]; @@ -90,6 +95,8 @@ data_read(void) route_head *route = NULL; int n; char lathemi, lonhemi; + char tbuf[20]; + char nbuf[20]; read_as_degrees = 0; @@ -100,19 +107,40 @@ data_read(void) switch (ibuf[0]) { case 'W': - sscanf(ibuf, "W %6c %c%lf %c%lf %s %s %ld", - name, &latdir, &lat, &londir, &lon, - date, time, &alt); + time[0] = 0; + date[0] = 0; + desc[0] = 0; + alt = -9999; + sscanf(ibuf, "W %6c %s %s %s %s %ld", + name, tbuf, nbuf, date, time, &alt); if (alt == -9999) { alt = unknown_alt; } - sscanf(&ibuf[60], "%40c", - desc); + + if (comment_col) { + strncpy(desc, &ibuf[comment_col], sizeof(desc)-1); + } else { + desc[0] = 0; + } + + symnum = 18; - sscanf(&ibuf[116], "%d", - &symnum); - desc[sizeof(desc)-1] = '\0'; + if (sym_col) { + symnum = atoi(&ibuf[sym_col]); + } + + // If we have explicit columns for lat and lon, + // copy those entire words (warning: no spaces) + // into the respective coord buffers. + if (lat_col) { + sscanf(tbuf, "%s", ibuf + lat_col); + } + if (lon_col) { + sscanf(nbuf, "%s", ibuf + lon_col); + } + name[sizeof(name)-1] = '\0'; + desc[sizeof(desc)-1] = '\0'; wpt_tmp = waypt_new(); wpt_tmp->altitude = alt; @@ -126,12 +154,17 @@ data_read(void) } wpt_tmp->icon_descr = gt_find_desc_from_icon_number(symnum, PCX, NULL); - if (latdir == 'S') lat = -lat; - if (londir == 'W') lon = -lon; - if (read_as_degrees) { + if (read_as_degrees || read_gpsu) { + human_to_dec(tbuf, &lat, &lon, 1); + human_to_dec(nbuf, &lat, &lon, 2); + wpt_tmp->longitude = lon; wpt_tmp->latitude = lat; } else { + lat = atof(&tbuf[1]); + lon = atof(&nbuf[1]); + if (tbuf[0] == 'S') lat = -lat; + if (nbuf[0] == 'W') lon = -lon; wpt_tmp->longitude = ddmm2degrees(lon); wpt_tmp->latitude = ddmm2degrees(lat); } @@ -209,9 +242,42 @@ data_read(void) break; case 'U': read_as_degrees = ! strncmp("LAT LON DEG", ibuf + 3, 11); + if (strstr(ibuf, "UTM")) { + fatal (MYNAME ": UTM is not supported.\n"); + } + break; + // GPSU is apparently PCX but with a different definition + // of "LAT LON DM" - unlike the other, it actually IS decimal + // minutes. + case 'I': + read_gpsu = ! (strstr(ibuf, "GPSU") == NULL) ; break; + // This is a format specifier. Use this line to figure out + // where our other columns start. + case 'F': { + int col; + sym_col = 0; + char *i = ibuf; + for (col = 0, i = ibuf; *i; col++, i++) { + if (0 == case_ignore_strncmp(i, "comment", 7)) { + comment_col = col; + } + if (0 == case_ignore_strncmp(i, "symbol", 6)) { + sym_col = col; + } + if (0 == case_ignore_strncmp(i, "latitude", 8)) { + lat_col = col; + } + if (0 == case_ignore_strncmp(i, "longitude", 9)) { + lon_col = col; + } + } + } + break; default: + break; ; + } } } diff --git a/reference/gpsutil-1.pcx b/reference/gpsutil-1.pcx new file mode 100644 index 000000000..26997a30f --- /dev/null +++ b/reference/gpsutil-1.pcx @@ -0,0 +1,23 @@ +H SOFTWARE NAME & VERSION +I GPSU 4.20 01 REGISTERED to 'THIS FILE CREATED BY HAND FOR GPSBABEL TEST' +S DateFormat=dd/mm/yyyy +S Timezone=+01:00 +S Units=N,M +S SymbolSet=0 + +H R DATUM +M E WGS 84 100 0.0000000E+00 0.0000000E+00 0 0 0 + +H COORDINATE SYSTEM +U LAT LON DM + +F ID---- Latitude Longitude T O Comment +W GCEBB N35°58.3220' W087°08.0820' I E Mountain Bike Heaven by susy1313 +W GC1A37 N36°05.4410' W086°40.7730' I E The Troll by a182pilot & Family +W GC1C2B N35°59.7760' W086°37.2070' I E Dive Bomber by JoGPS & family +W GC25A9 N36°02.3090' W086°38.9170' I E FOSTER by JoGPS & Family +W GC2723 N36°06.7310' W086°44.5060' I E Logan Lighthouse by JoGps & Family +W GC2B71 N36°03.8450' W086°47.4310' I E Ganier Cache by Susy1313 +W GC309F N36°05.2660' W086°48.5840' I E Shy's Hill by FireFighterEng33 +W GC317A N36°03.4500' W086°53.5200' I E GittyUp by JoGPS / Warner Parks +W GC317D N36°04.9680' W086°52.0370' I E Inlighting by JoGPS / Warner Parks diff --git a/testo b/testo index 9e09220a7..d43841c42 100755 --- a/testo +++ b/testo @@ -159,6 +159,9 @@ compare ${TMPDIR}/mm.gps ${TMPDIR}/gu.wpt ${PNAME} -t -i gpx -f ${REFERENCE}/track/tracks.gpx -o pcx -F ${TMPDIR}/pcx.trk ${PNAME} -t -i pcx -f ${REFERENCE}/track/pcx.trk -o pcx -F ${TMPDIR}/pcx2.trk compare ${TMPDIR}/pcx.trk ${TMPDIR}/pcx2.trk +# GPSUtil strain - hand crafted, but based on problem report. +${PNAME} -i pcx -f reference/gpsutil-1.pcx -o pcx -F ${TMPDIR}/mm-2.pcx +compare ${TMPDIR}/mm-2.pcx ${TMPDIR}/mm.pcx # # Magellan file format -- 2.30.2